package com.redpig.config;

import com.redpig.security.filter.JwtAuthenticationTokenFilter;
import com.redpig.security.filter.LoginAuthenticationFilter;
import com.redpig.security.handler.NoAuthAccessDeniedHandler;
import com.redpig.security.handler.LoginFailureHandler;
import com.redpig.security.handler.LoginSuccessHandler;
import com.redpig.security.manager.MenuAccessDecisionManager;
import com.redpig.security.manager.MenuFilterInvocationSecurityMetadataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Slf4j
@EnableWebSecurity
public class SecurityConfig {

    @Autowired
    MenuFilterInvocationSecurityMetadataSource menuFilterInvocationSecurityMetadataSource;

    @Autowired
    MenuAccessDecisionManager menuAccessDecisionManager;

    @Autowired
    NoAuthAccessDeniedHandler noAuthAccessDeniedHandler;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        http.authorizeRequests()
            .antMatchers("/register","/login","/unAuth","/user/refreshToken").permitAll() //匿名可以访问
            .anyRequest().authenticated()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setSecurityMetadataSource(menuFilterInvocationSecurityMetadataSource); //动态获取url权限配置
                        object.setAccessDecisionManager(menuAccessDecisionManager); //权限判断
                        return object;
                    }
                })
        .and()
            //将JWT拦截器添加到UsernamePasswordAuthenticationFilter之前
            .addFilterBefore(new JwtAuthenticationTokenFilter(),UsernamePasswordAuthenticationFilter.class) //登录之前验证token 从token中获取到登录凭证
            .addFilterAt(loginAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) //重写登录
        .formLogin()
            .successHandler(new LoginSuccessHandler())
            .failureHandler(new LoginFailureHandler())

        .and()
            .exceptionHandling().accessDeniedHandler(noAuthAccessDeniedHandler)
        .and()
            .csrf().disable();
        return http.build();
    }

    @Resource
    AuthenticationConfiguration authenticationConfiguration;

    @Bean
    public LoginAuthenticationFilter loginAuthenticationFilter() throws Exception {
        LoginAuthenticationFilter filter = new LoginAuthenticationFilter();
        filter.setAuthenticationSuccessHandler(new LoginSuccessHandler());
        filter.setAuthenticationFailureHandler(new LoginFailureHandler());
        //LoginAuthenticationFilter 中需要使用到AuthenticationManager 不加会出现空指针
        filter.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
        return filter;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
}
